/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.samples.rtp;

import javax.media.protocol.DataSource;
import javax.media.rtp.Participant;
import javax.media.rtp.RTPConnector;
import javax.media.rtp.RTPControl;
import javax.media.rtp.RTPManager;
import javax.media.rtp.ReceiveStream;
import javax.media.rtp.ReceiveStreamListener;
import javax.media.rtp.event.ByeEvent;
import javax.media.rtp.event.NewReceiveStreamEvent;
import javax.media.rtp.event.ReceiveStreamEvent;
import javax.media.rtp.event.RemotePayloadChangeEvent;
import javax.media.rtp.event.StreamMappedEvent;
import javax.media.rtp.event.TimeoutEvent;

/**
 * This Receiver class is used to receive media streams from a NaradaBrokering broker
 * and play the received stream in a window.
 * It can receive and play many streams. There is no limit on that.
 * It waits indefinetely. It should be stopped by Control C
 * When the player window is closed, it still does not close
 *
 * @author Ahmet Uyar
 * $Date$
 */
public class Receiver implements ReceiveStreamListener{

   private RTPManager rtpManager;
   private RTPConnector connector;

   /**
    * construct a receiver with a given Connector
    */
   public Receiver(RTPConnector connector) {
      this.connector = connector;
   }

   /**
   * starts the receiver, returns null if successfull
   * otherwise returns a String explaining the failure reason
   */
   public String initialize() {

      try {
         rtpManager = (RTPManager) RTPManager.newInstance();
         rtpManager.addReceiveStreamListener(this);
         rtpManager.initialize(connector);

      } catch (Exception e){
         e.printStackTrace();
         return "Cannot create the RTP Session: " + e.getMessage();
      }

      return null;
   }

    /**
     * Close the RTPManager
     */
    public void close() {

      // close the RTP session.
      if(rtpManager != null){
         rtpManager.removeTargets( "Closing session.");
         rtpManager.dispose();
         rtpManager = null;
      }
    }

    /**
     * ReceiveStreamListener
     */
    public synchronized void update( ReceiveStreamEvent evt) {

      Participant participant = evt.getParticipant();
      ReceiveStream stream = evt.getReceiveStream();

      if (evt instanceof RemotePayloadChangeEvent) {

         System.err.println("Received an RTP PayloadChangeEvent. Does nothing.");
      }else if (evt instanceof NewReceiveStreamEvent) {

         try {
            stream = ((NewReceiveStreamEvent)evt).getReceiveStream();

            DataSource ds = stream.getDataSource();
            new PlayerWindow(ds);

            // Find out the formats.
            RTPControl ctl = (RTPControl)ds.getControl("javax.media.rtp.RTPControl");
            if (ctl != null){
               System.err.println("---- Recevied new RTP stream. Format is " + ctl.getFormat()+"  ssrc: "+stream.getSSRC());
            }else{
               System.err.println("---- Recevied new RTP stream. Format is not known yet. ssrc: "+stream.getSSRC());
            }

         } catch (Exception e) {
            System.err.println("NewReceiveStreamEvent exception " + e.getMessage());
            e.printStackTrace();
            return;
         }

      }else if (evt instanceof StreamMappedEvent) {

            // Find out the formats.
            RTPControl ctl = (RTPControl)stream.getDataSource().getControl("javax.media.rtp.RTPControl");
            if (ctl != null)
               System.err.println("---- The previously unidentified stream is " + ctl.getFormat());

      }else if (evt instanceof ByeEvent) {
         if(participant != null)
            System.err.println("  - Got \"bye\" from: " + participant.getCNAME()+"This rtp session is closed.");

      }else if(evt instanceof TimeoutEvent){

         if(participant != null){
            System.err.println("  - timeout occured for: " + participant.getCNAME());
         }else{
            System.out.println("  - timeout occured");
         }
      }
   }

   /**
    * start a Receiver with the given paramaters
    */
   public static void startReceiver(String brokerIP, int brokerPort, int topicNumber){

      NaradaRTPConnector connector = new NaradaRTPConnector(brokerIP, brokerPort, topicNumber);
      Receiver cr = new Receiver(connector);
      String result = cr.initialize();
      if (result != null) {
         System.err.println("Failed to initialize the session. The error message is: "+result);
      }else{
         System.err.println("  - Subscried to the topic: "+topicNumber);
         System.err.println("  - Waiting for video stream to arrive....");
      }
   }

   /**
    *
    * @param args
    * @throws java.io.IOException
    */
   public static void main(String args[]) throws java.io.IOException {

      if(args.length != 3){
         printUsage();
         return;
      }

      int brokerPort = Integer.parseInt( args[1] );
      int topicNumber = Integer.parseInt( args[2] );

      startReceiver(args[0], brokerPort, topicNumber);

      //wait here
      while( true )
         try{
         Thread.sleep(10000);
      }catch(Exception e){
         e.printStackTrace();
      }
   }

   public static void printUsage(){
      System.out.println("java cgl.narada.samples.rtp.Receiver <Broker IP> <Broker Port> <Topic Number>");
   }

}// end of Receiver
